/* 
 * Copyright [2018] [Alex/libo(liboms@hotmail.com)]
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.guava.validator;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.hyts.guava.config.ValidateConfig;
import com.hyts.guava.exception.Exceptions;

/** 
 * @title Validates.java  
 * @package com.hyts.guava.validator  
 * @description 预执行操作开发对象，一般用于操作参数校验工作，
 * 				判断参数是否符合要求的功能以及校验。
 * 				基于Preconditions类信息封装,strategy模式操作
 * @see com.google.common.base.Preconditions
 * @author libo/Alex
 * @email liboms@hotmail.com/liboware@163.com  
 * @date 2018年5月5日 
 * @version V1.0 
 */
public final class Validates {
	
	/**  
	 * <b>validateArgument：校验参数是否符合要求错误则直接报出IllegalArgumentException</b>
	 * <p>校验参数是否符合要求错误则直接报出IllegalArgumentException</p>
	 * @param validateExpression
	 * @exception IllegalArgumentException
	 */ 
	public static void validateArgument(boolean validateExpression) throws IllegalArgumentException{
		Preconditions.checkArgument(validateExpression);
	}
	
	/**  
	 * <b>validateArgumentNoneThrow(不推荐)：校验参数是否符合要求错误则直接报出IllegalArgumentException</b>
	 * <p>校验参数是否符合要求错误则直接报出IllegalArgumentException</p>
	 * @param validateExpression
	 * @exception IllegalArgumentException
	 */ 
	public static boolean validateArgumentNoneThrow(boolean validateExpression){
		try {
			Preconditions.checkArgument(validateExpression);
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	
	/**  
	 * <b>validateArgument：校验参数是否符合要求错误</b>
	 * <p>
	 * 	   校验参数是否符合要求错误则直接报出IllegalArgumentException
	 *    
	 * </p>
	 * @param validateExpression
	 * @exception IllegalArgumentException
	 */ 
	public static void validateArgument(boolean validateExpression,String message) throws IllegalArgumentException{
		Preconditions.checkArgument(validateExpression,message);
	}
	
	/**  
	 * <b>validateArgumentNoneThrow(不推荐)：校验参数是否符合要求错误则直接报出IllegalArgumentException</b>
	 * <p>校验参数是否符合要求错误则直接报出IllegalArgumentException</p>
	 * @param validateExpression
	 * @exception IllegalArgumentException
	 */ 
	public static boolean validateArgumentNoneThrow(boolean validateExpression,String message){
		try {
			validateArgument(validateExpression,message);
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	
	/**  
	 * <b>validateArgument:主要校验空操作参数</b>
	 * <p>校验参数表达式 抛出异常</p>
	 * @param param
	 * @param message
	 * @return
	 * @exception
	 */ 
	public static void validateArgument(Object param,String message) throws NullPointerException {
		 Preconditions.checkNotNull(param,Strings.isNullOrEmpty(message)
					?ValidateConfig.PARAM_NULL.getMessage():message);
	}
	
	/**  
	 * <b>validateArgumentNoneThrow(不推荐):主要校验空操作参数</b>
	 * <p>校验参数表达式 不抛出异常只返回true/false</p>
	 * @param param
	 * @param message
	 * @exception
	 */ 
	public static boolean validateArgumentNoneThrow(Object param,String message) {
		 try {
			Preconditions.checkNotNull(param,Strings.isNullOrEmpty(message)
						?ValidateConfig.PARAM_NULL.getMessage():message);
		} catch (Exception e) {
			return false;
		}
		 return true;
	}
	
	
	/**  
	 * <b>validateArgument:主要校验空操作参数</b>
	 * <p>校验参数表达式 抛出异常</p>
	 * @param param
	 * @return
	 * @exception
	 */ 
	public static void validateArgument(Object param) throws NullPointerException {
		 Preconditions.checkNotNull(param);
	}
	
	/**  
	 * <b>validateArgumentNoneThrow(不推荐):主要校验空操作参数</b>
	 * <p>校验参数表达式 不抛出异常只返回true/false</p>
	 * @param param
	 * @exception
	 */ 
	public static boolean validateArgumentNoneThrow(Object param) {
		 try {
			Preconditions.checkNotNull(param);
		} catch (Exception e) {
			return false;
		}
		 return true;
	}
	
	/**  
	 * <b>validateCollection:校验集合（校验范围）</b>
	 * <p></p>
	 * @param param
	 * @param index 索引指针位置
	 * @exception NullPointerException,IndexOutOfBoundsException
	 */ 
	public static int validateRange(Object param,int index) throws NullPointerException,IndexOutOfBoundsException {
		validateArgument(param);
		//校验类型判断操作
		try {
			if(param instanceof List) {
				return Preconditions.checkElementIndex(index, ((List) param).size());
			}else if(param.getClass().isArray()) {
				return Preconditions.checkElementIndex(index,Arrays.asList(param).size());
			}else if(param instanceof String) {
				return Preconditions.checkElementIndex(index,param.toString().length());
			}
		} catch (Exception e) {
			Throwables.propagateIfPossible(e, IndexOutOfBoundsException.class);
			Exceptions.throwRuntimeException(e);
			return -1;
		}
		return -1;
	}
	
	/**  
	 * <b>validateCollection:校验集合（校验范围）</b>
	 * <p></p>
	 * @param param
	 * @param index 索引指针位置
	 * @exception NullPointerException
	 */ 
	public static int validateRangeNoneThrow(Object param,int index) throws NullPointerException{
		validateArgument(param);
		//校验类型判断操作
		try {
			if(param instanceof List) {
				return Preconditions.checkElementIndex(index, ((List) param).size());
			}else if(param.getClass().isArray()) {
				return Preconditions.checkElementIndex(index,Arrays.asList(param).size());
			}else if(param instanceof String) {
				return Preconditions.checkElementIndex(index,param.toString().length());
			}
		} catch (Exception e) {
			/*Throwables.propagateIfPossible(e, IndexOutOfBoundsException.class);
			Exceptions.throwRuntimeException(e);*/
		}
		return -1;
	}
	
	/**  
	 * <b>TODO(方法功能的描述)</b>
	 * <p>TODO(这里用一句话描述这个方法的作用)</p>
	 * @param param
	 * @param start
	 * @param end
	 * @throws NullPointerException
	 * @exception
	 */ 
	public static void validateRange(Object param,int start,int end) throws NullPointerException{
		validateArgument(param);
		//校验类型判断操作
		try {
			if(param instanceof List) {
				Preconditions.checkPositionIndexes(start, end,((List) param).size());
			}else if(param.getClass().isArray()) {
				Preconditions.checkPositionIndexes(start, end,Arrays.asList(param).size());
			}else if(param instanceof String) {
				Preconditions.checkPositionIndexes(start, end,param.toString().length());
			}
		} catch (Exception e) {
			Throwables.propagateIfPossible(e, IndexOutOfBoundsException.class);
			Exceptions.throwRuntimeException(e);
		}
	}
	
	/**  
	 * <b>validateRangeNoneThrow:不进行抛出错误提示</b>
	 * <p>TODO(这里用一句话描述这个方法的作用)</p>
	 * @param param
	 * @param start
	 * @param end
	 * @param desc
	 * @return
	 * @throws NullPointerException
	 * @exception
	 */ 
	public static int validateRangeNoneThrow(Object param,int limited,String desc) throws NullPointerException{
			validateArgument(param);
			//校验类型判断操作
			try {
				if(param instanceof List) {
					return badPositionIndex(limited,((List) param).size(),desc);
				}else if(param.getClass().isArray()) {
					return badPositionIndex(limited,Arrays.asList(param).size(),desc);
				}else if(param instanceof String) {
					return badPositionIndex(limited,param.toString().length(),desc);
				}
		} catch (Exception e) {
			return -1;
		}
		return -1;
	}
	
	/**  
	 * <b>TODO(方法功能的描述)</b>
	 * <p>TODO(这里用一句话描述这个方法的作用)</p>
	 * @param param
	 * @param limited
	 * @param desc
	 * @return
	 * @throws NullPointerException
	 * @exception
	 */ 
	public static void validateRange(Object param,int limited,String desc) throws NullPointerException{
		validateArgument(param);
		//校验类型判断操作
		try {
			if(param instanceof List) {
				 badPositionIndex(limited,((List) param).size(),desc);
			}else if(param.getClass().isArray()) {
				 badPositionIndex(limited,Arrays.asList(param).size(),desc);
			}else if(param instanceof String) {
				 badPositionIndex(limited,param.toString().length(),desc);
			}
	} catch (Exception e) {
		Exceptions.throwRuntimeException(e);
	}
}
	
	
	
	/**  
	 * <b>TODO(方法功能的描述)</b>
	 * <p>TODO(这里用一句话描述这个方法的作用)</p>
	 * @param index
	 * @param size
	 * @param desc
	 * @return
	 * @exception
	 */ 
	private static int badPositionIndex(int index, int size, String desc) {
		 // Carefully optimized for execution by hotspot (explanatory comment above)
	    if (index < 0 || index >= size) {
	      throw new IndexOutOfBoundsException(poositionIndex(index, size, desc));
	    }
	    return index;
	}
	
	private static String poositionIndex(int index, int size, String desc){
		if (index < 0) {
		    return format("%s (%s) must not be negative", desc, index);
		} else if (size < 0) {
		    throw new IllegalArgumentException("negative size: " + size);
	    } else { // index > size
		    return format("%s (%s) must not be greater than size (%s)", desc, index, size);
		}
	}
	
	static String format(String template,  Object... args) {
		    template = String.valueOf(template); // null -> "null"

		    // start substituting the arguments into the '%s' placeholders
		    StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
		    int templateStart = 0;
		    int i = 0;
		    while (i < args.length) {
		      int placeholderStart = template.indexOf("%s", templateStart);
		      if (placeholderStart == -1) {
		        break;
		      }
		      builder.append(template.substring(templateStart, placeholderStart));
		      builder.append(args[i++]);
		      templateStart = placeholderStart + 2;
		    }
		    builder.append(template.substring(templateStart));

		    // if we run out of placeholders, append the extra args in square braces
		    if (i < args.length) {
		      builder.append(" [");
		      builder.append(args[i++]);
		      while (i < args.length) {
		        builder.append(", ");
		        builder.append(args[i++]);
		      }
		      builder.append(']');
		    }
		return builder.toString();
	} 
	
	/**  
	 * <b>validateState:校验状态操作</b>
	 * <p>校验状态信息</p>
	 * @param stateCompareExp
	 * @param message
	 * @throws IllegalStateException
	 * @exception
	 */ 
	public static void validateState(boolean stateCompareExp,String message) throws IllegalStateException {
		Preconditions.checkState(stateCompareExp,
				Strings.isNullOrEmpty(message)?ValidateConfig.STATE_WRONG.getMessage():message);
	}
	
	/**  
	 * <b>validateState:校验状态操作</b>
	 * <p>校验状态信息</p>
	 * @param stateCompareExp
	 * @param message
	 * @throws IllegalStateException
	 * @exception
	 */ 
	public static boolean validateStateNoneThrow(boolean stateCompareExp,String message) throws NullPointerException{
		try {
			Preconditions.checkState(stateCompareExp,message);
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	
	public static void main(String[] args) {
		//validateState(false,"qwe");
		//validateStateNoneThrow(false,"状态出现问题");
		validateRange(Arrays.asList(new String[]{"1","2"}),1,"des");
	}
}
